home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  47.3 KB  |  1,888 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 41
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. /**********************************************************************
  4.  * various useful functions
  5.  **********************************************************************/
  6. #pragma load EUDORA_LOAD
  7. #pragma segment Util
  8. #ifdef    KERBEROS
  9. #include                <krb.h>
  10. #endif
  11.  
  12. char BitTable[] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
  13. pascal Boolean PasswordFilter(DialogPtr dgPtr,EventRecord *event,short *item);
  14. void CopyPassword(UPtr password);
  15. int ResetPassword(void);
  16. UHandle PwChars=nil;
  17. void NukeMenuItem(MenuHandle mh,short item);
  18.  
  19. /**********************************************************************
  20.  * Allocate a handle, and write zeroes all over it
  21.  **********************************************************************/
  22. Handle NewZHandle(long size)
  23. {
  24.     Handle theHandle;
  25.     
  26.     /*
  27.      * allocate it
  28.      */
  29.     if ((theHandle=NuHandle(size))==nil)
  30.         return(nil);
  31.         
  32.     /*
  33.      * zero it
  34.      */
  35.     WriteZero(*theHandle,size);
  36.     
  37.     /*
  38.      * all done
  39.      */
  40.     return(theHandle);
  41. }
  42.  
  43. /**********************************************************************
  44.  * write zeroes over an area of memory
  45.  **********************************************************************/
  46. void WriteZero(UPtr pointer,long size)
  47. {
  48.     while (size--) *pointer++ = 0;
  49. }
  50.  
  51. /**********************************************************************
  52.  * initialize all the mac managers
  53.  **********************************************************************/
  54. void MacInitialize(int masterCount, long ensureStack)
  55. {
  56.     EventRecord event;
  57.     
  58.     if (*(long *)CurStackBase - *(long *)ApplLimit <ensureStack)
  59.         SetApplLimit((UPtr)(*(long *)CurStackBase - ensureStack));
  60.     MaxApplZone();
  61.     while (masterCount--) MoreMasters();
  62.     FlushEvents (everyEvent - diskMask, 0 );
  63.     InitGraf (&qd.thePort);
  64.     InitFonts ();
  65.     InitWindows ();
  66.     InitMenus ();
  67.     TEInit ();
  68.     InitDialogs (nil);        /* no restart proc */
  69.     InitCursor ();
  70.     InitPack(stdFile);
  71.     InitPack(bdConv);
  72.     InitPack(intUtil);
  73.     WNE(nullEvent,&event,0);
  74.     WNE(nullEvent,&event,0);
  75.     WNE(nullEvent,&event,0);
  76. }
  77.  
  78. /**********************************************************************
  79.  * turn a font name into a font id; if the name is not found, use ApplFont
  80.  **********************************************************************/
  81. GetFontID(UPtr theName)
  82. {
  83.     short theID;
  84.     Str255 systemName;
  85.     
  86.     GetFNum(theName,&theID);
  87.     if (!theID)
  88.     {
  89.         GetFontName(0,systemName);
  90.         return (EqualString(theName,systemName,FALSE,FALSE) ? 0: applFont);
  91.     }
  92.     else
  93.         return (theID);
  94. }
  95. /**********************************************************************
  96.  * get an event, giving time to system tasks as necessary
  97.  **********************************************************************/
  98. Boolean GrabEvent(EventRecord *theEvent)
  99. {
  100.     Boolean result;
  101.     
  102.     /*
  103.      * get the event
  104.      */
  105.     result = WNE(everyEvent,theEvent,InBG ? 300L : 10L);
  106.  
  107.     /*
  108.      * handle special keys
  109.      */
  110.     if (theEvent->what==keyDown || theEvent->what==autoKey)
  111.         SpecialKeys(theEvent);
  112.     
  113.     /*
  114.      * gd dialog manager
  115.      */
  116.     if (!result && IsDialogEvent(theEvent)) DoModelessEvent(theEvent);
  117.  
  118.     return(result);
  119. }
  120.  
  121. /**********************************************************************
  122.  * Check or uncheck a font size in the font menu
  123.  **********************************************************************/
  124. void CheckFontSize(int menu,int size,Boolean check)
  125. {
  126.     Str255 aString;
  127.     Str255 itemString;
  128.     MenuHandle mHandle;
  129.     short item;
  130.     
  131.     /*
  132.      * turn the font size into a string
  133.      */
  134.     NumToString((long)size,aString);
  135.         
  136.     /*
  137.      * get a copy of the menu handle
  138.      */
  139.     mHandle = GetMHandle(menu);
  140.     
  141.     /*
  142.      * look for the proper item
  143.      */
  144.     for (item = 1; ;item++)
  145.     {
  146.         GetItem(mHandle,item,itemString);
  147.         if (itemString[1]=='-') break;
  148.         if (EqualString(aString,itemString,FALSE,FALSE))
  149.         {
  150.             CheckItem(mHandle,item,check);
  151.             break;
  152.         }
  153.     }
  154. }
  155. /**********************************************************************
  156.  * check (or uncheck) a font name in a menu.    If check, also outline sizes
  157.  **********************************************************************/
  158. void CheckFont(int menu,int fontID,Boolean check)
  159. {
  160.     Str255 aString;
  161.     Str255 itemString;
  162.     MenuHandle mHandle;
  163.     short item;
  164.     
  165.     /*
  166.      * turn the font id into a font name
  167.      */
  168.     GetFontName(fontID,aString);
  169.     
  170.     /*
  171.      * get a copy of the menu handle
  172.      */
  173.     mHandle = GetMHandle(menu);
  174.     
  175.     /*
  176.      * look for the proper item
  177.      */
  178.     for (item = 1; ;item++)
  179.     {
  180.         GetItem(mHandle,item,itemString);
  181.         if (itemString[1]=='-') break;        /* skip the sizes */
  182.     }
  183.     for (item++; ;item++)
  184.     {
  185.         GetItem(mHandle,item,itemString);
  186.         if (EqualString(aString,itemString,FALSE,FALSE))
  187.         {
  188.             CheckItem(mHandle,item,check);
  189.             if (check) OutlineFontSizes(menu,fontID);
  190.             break;
  191.         }
  192.     }
  193. }
  194.  
  195. /**********************************************************************
  196.  * outline sizes of a font in a menu
  197.  **********************************************************************/
  198. void OutlineFontSizes(int menu,int fontID)
  199. {
  200.     Str255 aString;
  201.     MenuHandle mHandle;
  202.     short item;
  203.     long aSize;
  204.     
  205.     /*
  206.      * get a copy of the menu handle
  207.      */
  208.     mHandle = GetMHandle(menu);
  209.  
  210.     /*
  211.      * outline'em
  212.      */
  213.     for (item = 1; ;item++)
  214.     {
  215.         GetItem(mHandle,item,aString);
  216.         if (aString[1]=='-') break;     /* end of sizes? */
  217.         /*
  218.          * turn text into size
  219.          */
  220.         StringToNum(aString,&aSize);
  221.         
  222.         /*
  223.          * does it exist?
  224.          */
  225.         if (RealFont(fontID,(short)aSize))
  226.             SetItemStyle(mHandle,item,outline);
  227.         else
  228.             SetItemStyle(mHandle,item,nil);
  229.     }
  230. }
  231.  
  232. /**********************************************************************
  233.  * figure out the appropriate leading for a font
  234.  **********************************************************************/
  235. int GetLeading(int fontID,int fontSize)
  236. {
  237.     FMInput fInInfo;
  238.     FMOutput *fOutInfo;
  239.     
  240.     /*
  241.      * set up the font input struct
  242.      */
  243.     fInInfo.family = fontID;
  244.     fInInfo.size = fontSize;
  245.     fInInfo.face = 0;
  246.     fInInfo.needBits = FALSE;
  247.     fInInfo.device = 0;
  248.     fInInfo.numer.h = fInInfo.numer.v = 1;
  249.     fInInfo.denom.h = fInInfo.denom.v = 1;
  250.     
  251.     
  252.     /*
  253.      * get the actual info
  254.      */
  255.     fOutInfo = FMSwapFont(&fInInfo);
  256.     
  257.     /*
  258.      * yokey-dokey
  259.      */
  260.     return(((fOutInfo->leading + fOutInfo->ascent + fOutInfo->descent)*fOutInfo->numer.v)/fOutInfo->denom.v);
  261. }
  262.  
  263. /**********************************************************************
  264.  * find width of largest char in font
  265.  **********************************************************************/
  266. int GetWidth(int fontID,int fontSize)
  267. {
  268. #ifdef FONTMGR
  269.     FMInput fInInfo;
  270.     FMOutput *fOutInfo;
  271.     
  272.     /*
  273.      * set up the font input struct
  274.      */
  275.     fInInfo.family = fontID;
  276.     fInInfo.size = fontSize;
  277.     fInInfo.face = 0;
  278.     fInInfo.needBits = FALSE;
  279.     fInInfo.device = 0;
  280.     fInInfo.numer.h = fInInfo.numer.v = 1;
  281.     fInInfo.denom.h = fInInfo.denom.v = 1;
  282.     
  283.     
  284.     /*
  285.      * get the actual info
  286.      */
  287.     fOutInfo = FMSwapFont(&fInInfo);
  288.     
  289.     /*
  290.      * yokey-dokey
  291.      */
  292.     return((fOutInfo->widMax * fOutInfo->numer.h)/fOutInfo->denom.h);
  293. #else
  294.  
  295.     GrafPtr oldPort;
  296.     GrafPort aPort;
  297.     int width;
  298.     
  299.     GetPort(&oldPort);
  300.     
  301.     OpenPort(&aPort);
  302.     TextFont(fontID);
  303.     TextSize(fontSize);
  304.     width = CharWidth('0');
  305.     
  306.     ClosePort(&aPort);
  307.     SetPort(oldPort);
  308.     
  309.     return(width);
  310. #endif
  311. }
  312.  
  313. /**********************************************************************
  314.  * find descent font
  315.  **********************************************************************/
  316. int GetDescent(int fontID,int fontSize)
  317. {
  318.     FMInput fInInfo;
  319.     FMOutput *fOutInfo;
  320.     
  321.     /*
  322.      * set up the font input struct
  323.      */
  324.     fInInfo.family = fontID;
  325.     fInInfo.size = fontSize;
  326.     fInInfo.face = 0;
  327.     fInInfo.needBits = FALSE;
  328.     fInInfo.device = 0;
  329.     fInInfo.numer.h = fInInfo.numer.v = 1;
  330.     fInInfo.denom.h = fInInfo.denom.v = 1;
  331.     
  332.     
  333.     /*
  334.      * get the actual info
  335.      */
  336.     fOutInfo = FMSwapFont(&fInInfo);
  337.     
  338.     /*
  339.      * yokey-dokey
  340.      */
  341.     return((fOutInfo->descent * fOutInfo->numer.v)/fOutInfo->denom.v);
  342. }
  343.  
  344. /**********************************************************************
  345.  * find ascent font
  346.  **********************************************************************/
  347. int GetAscent(int fontID,int fontSize)
  348. {
  349.     FMInput fInInfo;
  350.     FMOutput *fOutInfo;
  351.     
  352.     /*
  353.      * set up the font input struct
  354.      */
  355.     fInInfo.family = fontID;
  356.     fInInfo.size = fontSize;
  357.     fInInfo.face = 0;
  358.     fInInfo.needBits = FALSE;
  359.     fInInfo.device = 0;
  360.     fInInfo.numer.h = fInInfo.numer.v = 1;
  361.     fInInfo.denom.h = fInInfo.denom.v = 1;
  362.     
  363.     
  364.     /*
  365.      * get the actual info
  366.      */
  367.     fOutInfo = FMSwapFont(&fInInfo);
  368.     
  369.     /*
  370.      * yokey-dokey
  371.      */
  372.     return((fOutInfo->ascent * fOutInfo->numer.v)/fOutInfo->denom.v);
  373. }
  374.  
  375. /**********************************************************************
  376.  * find fixed-width-ness of font
  377.  **********************************************************************/
  378. Boolean IsFixed(int fontID,int fontSize)
  379. {
  380.     FMInput fInInfo;
  381.     FMOutput *fOutInfo;
  382.     
  383.     /*
  384.      * set up the font input struct
  385.      */
  386.     fInInfo.family = fontID;
  387.     fInInfo.size = fontSize;
  388.     fInInfo.face = 0;
  389.     fInInfo.needBits = FALSE;
  390.     fInInfo.device = 0;
  391.     fInInfo.numer.h = fInInfo.numer.v = 1;
  392.     fInInfo.denom.h = fInInfo.denom.v = 1;
  393.     
  394.     
  395.     /*
  396.      * get the actual info
  397.      */
  398.     fOutInfo = FMSwapFont(&fInInfo);
  399.     
  400.     /*
  401.      * yokey-dokey
  402.      */
  403.     return((((FontRec *)(*fOutInfo->fontHandle))->fontType & fixedFont)==fixedFont);
  404. }
  405.  
  406. /**********************************************************************
  407.  * wait for the user to strike a modifier key
  408.  **********************************************************************/
  409. void AwaitKey(void)
  410. {
  411.     KeyMap kMap;
  412.     register long * k;
  413.     register long * kEnd;
  414.     
  415.     while (1)
  416.     {
  417.         GetKeys(&kMap);
  418.         for (k= &kMap,kEnd=k+sizeof(KeyMap)/sizeof(long); k<kEnd; k++)
  419.             if (*k) return;
  420.     }
  421. }
  422. /**********************************************************************
  423.  * change or add some data to the current resource file
  424.  **********************************************************************/
  425. void ChangePResource(UPtr theData,int theLength,long theType,int theID,UPtr theName)
  426. {
  427.     Handle aHandle;
  428.     
  429.     /*
  430.      * does the resource exist and reside in the topmost res file?
  431.      */
  432.     SetResLoad(FALSE);
  433.     aHandle = Get1Resource(theType,(short)theID);
  434.     SetResLoad(TRUE);
  435.     
  436.     if (aHandle)
  437.     {
  438.         /* must nuke the resource first */
  439.         RmveResource(aHandle);
  440.         DisposHandle(aHandle);
  441.     }
  442.         
  443.     AddPResource(theData, theLength, theType, theID, theName);
  444. }
  445.  
  446. /**********************************************************************
  447.  * add some data to the current resource file
  448.  **********************************************************************/
  449. void AddPResource(theData, theLength, theType, theID, theName)
  450. UPtr theData;          /* data to go into resource */
  451. int theLength;        /* number of bytes of data */
  452. long theType;         /* resource type */
  453. int theID;                /* resource id */
  454. UPtr theName;          /* name of resource */
  455. {
  456.     Handle aHandle;
  457.     
  458.     /*
  459.      * allocate the handle
  460.      */
  461.     aHandle = NuHandle((long)theLength);
  462.     if (aHandle == nil)
  463.         return;
  464.     
  465.     /*
  466.      * copy the data
  467.      */
  468.     BlockMove(theData,*aHandle,(long)theLength);
  469.     
  470.     /*
  471.      * add it
  472.      */
  473.     AddResource(aHandle,theType,theID,theName);
  474. }
  475.  
  476. /**********************************************************************
  477.  * ResourceCpy - copy a resource from one resource file to the other
  478.  **********************************************************************/
  479. int ResourceCpy(short toRef, short fromRef,long type,int id)
  480. {
  481.     int oldRef;
  482.     Handle resource;
  483.     Str255 name;
  484.     short attrs;
  485.     
  486.     oldRef = CurResFile();
  487.     UseResFile(toRef);
  488.     SetResLoad(false);
  489.     resource = GetResource(type,id); /* no sense loading it if it's wrong */
  490.     if (resource!=nil)
  491.     {
  492.         if (HomeResFile(resource)==toRef)
  493.         {
  494.             /*
  495.              * delete the old one first
  496.              */
  497.             RmveResource(resource);
  498.             DisposHandle(resource);
  499.             resource = nil;
  500.         }
  501.         else if (HomeResFile(resource)!=fromRef)
  502.         {
  503.             ReleaseResource(resource);        /* wrong one */
  504.             resource = nil;
  505.         }
  506.     }
  507.     
  508.     if (resource==nil)
  509.     {     
  510.         /*
  511.          * fetch from the proper file
  512.          */
  513.         UseResFile(fromRef);
  514.         resource = Get1Resource(type,id);
  515.         if (resource==nil) return(resNotFound);
  516.     }
  517.     
  518.     SetResLoad(True);                                     /* turn that goodie back on */
  519.     attrs = GetResAttrs(resource);            /* save attributes */
  520.     GetResInfo(resource,&id,&type,name);/* get the name */
  521.     HNoPurge(resource);                                 /* keep it right here */
  522.     LoadResource(resource);                         /* load it in  */
  523.     if (ResError()) return(ResError()); /* did that work? */
  524.     DetachResource(resource);                     /* break cnxn with old file */
  525.     UseResFile(toRef);                                    /* point at to resource file */
  526.     AddResource(resource,type,id,name); /* stick into new file */
  527.     if (ResError()) return(ResError()); /* did that work? */
  528.     SetResAttrs(resource,attrs);                /* restore attributes */
  529.     ChangedResource(resource);                    /* except it's been changed */
  530.     UseResFile(oldRef);                                 /* restore old res file */
  531.     
  532.     return(noErr);
  533. }
  534.  
  535. /**********************************************************************
  536.  * DrawTruncString - truncate and draw a string; restores string when done
  537.  **********************************************************************/
  538. void DrawTruncString(UPtr string,int len)
  539. {
  540.     int sLen = *string;
  541.     
  542.     if (sLen > len)
  543.     {
  544.         Byte save = string[len];
  545.         string[len] = '…';
  546.         *string = len;
  547.         DrawString(string);
  548.         *string = sLen;
  549.         string[len] = save;
  550.     }
  551.     else
  552.         DrawString(string);
  553. }
  554.  
  555. /**********************************************************************
  556.  * CalcTrunc - figure out how much of a string we can print to fit
  557.  * in a given width
  558.  **********************************************************************/
  559. int CalcTextTrunc(UPtr string,short length, short width,GrafPtr port)
  560. {
  561.     short tLen;
  562.     int cWidth;
  563.     GrafPtr oldPort;
  564.     
  565.     if (width<=0) return(0);
  566.     
  567.     GetPort(&oldPort);
  568.     SetPort(port);
  569.     
  570.     /*
  571.      * make an initial estimate
  572.      */
  573.     tLen = MIN(width/CharWidth(' '),length);
  574.     
  575.     /*
  576.      * if the string fits, ...
  577.      */
  578.     cWidth = TextWidth(string,0,tLen);
  579.     if (cWidth<width && tLen==length) {SetPort(oldPort);return(length);}
  580.     
  581.     /*
  582.      * if it's too short
  583.      */
  584.     if (cWidth<=width)
  585.     {
  586.         if (tLen<length)
  587.         {
  588.             tLen++;
  589.             while (TextWidth(string,0,tLen)<width && tLen<length) tLen++;
  590.             tLen--;
  591.         }
  592.     }
  593.     /*
  594.      * too long...
  595.      * (we do pretend there is always room for 1 character)
  596.      */
  597.     else
  598.         do
  599.         {
  600.             tLen--;
  601.             cWidth = TextWidth(string,0,tLen);
  602.         }
  603.         while (tLen && cWidth>width);
  604.     
  605.     SetPort(oldPort);
  606.     return (tLen ? tLen : 1);
  607. }
  608.  
  609. /**********************************************************************
  610.  * WhiteRect - draw white rectangle with a black border
  611.  **********************************************************************/
  612. void WhiteRect(Rect *r)
  613. {
  614.     Rect myR = *r;
  615.     
  616.     FrameRect(&myR);
  617.     InsetRect(&myR,1,1);
  618.     EraseRect(&myR);
  619. }
  620.  
  621. /************************************************************************
  622.  * WannaSave - find out of the user wants to save the contents of a window
  623.  ************************************************************************/
  624. int WannaSave(MyWindowPtr win)
  625. {
  626.     Str255 title;
  627.     
  628.     PCopy(title,*win->qWindow.titleHandle);
  629.     return(AlertStr(WANNA_SAVE_ALRT,Stop,title));
  630. }
  631.  
  632. /************************************************************************
  633.  * GetPassword - read a user's password
  634.  ************************************************************************/
  635. #ifdef    KERBEROS
  636. int GetPassword(void)
  637. #else
  638. int GetPassword(UPtr forString,UPtr word, int size, short prompt)
  639. #endif
  640. {
  641.     Str255 string;
  642.     DialogPtr dgPtr;
  643.     short item;
  644. #ifdef    KERBEROS
  645.     Str63 userName, args;
  646.     char    name[ANAME_SZ];
  647.     char    inst[INST_SZ];
  648.     char    realm[REALM_SZ];
  649.     CREDENTIALS     cr;
  650.     int     status;
  651. #endif
  652.  
  653. #ifdef    KERBEROS
  654.                 /* perhaps we're logged in already? */
  655.                 GetPOPInfo(userName,args);
  656.                 PtoCcpy(name, userName);
  657.  
  658.                 inst[0] = 0;
  659.                 if(0 != (status = krb_get_lrealm(realm, 1))) {
  660.                                 char        message[256];
  661.                                 
  662.                                 sprintf(message, "Couldn't log in: %s", krb_err_txt[status]);
  663.                                 c2pstr(message);
  664.                                 AlertStr(OK_ALRT,Caution,message);
  665.                                 return 1;
  666.                                 }
  667.                 status = krb_get_cred(name, inst, realm, "krbtgt", realm, realm, &cr);
  668.                 if(!status) {     /* credentials exist */
  669.                                 return 0;
  670.                                 }
  671.                 /* otherwise we need to get the password */
  672. #endif
  673.     
  674.     if (!MommyMommy(ATTENTION,nil)) return(PASSWORD_CANCEL);
  675.     GetRString(string,prompt);
  676.     MyParamText(forString,string,"","");
  677.     ThirdCenterDialog(PASSWORD_DLOG);
  678.     if ((dgPtr = GetNewMyDialog(PASSWORD_DLOG,nil,InFront,ThirdCenterDialog))==nil)
  679.     {
  680.         WarnUser(GENERAL,MemError());
  681.         return(PASSWORD_CANCEL);
  682.     }
  683.     if (!(CurrentModifiers()&alphaLock)) HideDItem(dgPtr,PASSWORD_WARNING);
  684.     
  685.     ShowWindow(dgPtr);
  686.     HiliteButtonOne(dgPtr);
  687.     do
  688.     {
  689.         SetDIText(dgPtr,PASSWORD_WORD,"");
  690.         SelIText(dgPtr,PASSWORD_WORD,0,INFINITY);
  691.         if (ResetPassword()) {item=PASSWORD_CANCEL; break;}
  692.         PushCursor(arrowCursor);
  693.         ModalDialog(PasswordFilter,&item);
  694.         PopCursor();
  695.         CopyPassword(string);
  696.     }
  697.     while (item==PASSWORD_OK && !*string);
  698.     DisposDialog(dgPtr);
  699.     InBG = False; 
  700.     if (item==PASSWORD_OK)
  701.     {
  702. #ifndef KERBEROS
  703.         if (*string > size-1) *string = size - 1;
  704.         PCopy(word,string);
  705. #else
  706.                 /* login */
  707.                 p2cstr(string);
  708.                 status = krb_get_pw_in_tkt(name, inst, realm, "krbtgt", realm, 96,
  709.                                                                                                                                 (char *)string);
  710.                 if(status != KSUCCESS) {
  711.                                 char        message[256];
  712.                                 
  713.                                 sprintf(message, "Login failed: %s", krb_err_txt[status]);
  714.                                 c2pstr(message);
  715.                                 AlertStr(OK_ALRT,Caution,message);
  716.                                 return 1;
  717.                                 }
  718. #endif
  719.     }
  720.     return(item!=PASSWORD_OK);
  721. }
  722.  
  723. /************************************************************************
  724.  * ResetPassword - get the password routines ready
  725.  ************************************************************************/
  726. int ResetPassword(void)
  727. {
  728.     if (!PwChars)
  729.         PwChars = NuHandle(256L);
  730.     else if (!*PwChars)
  731.         ReallocHandle(PwChars,256L);
  732.     if (!PwChars || !*PwChars) return(MemError());
  733.     HNoPurge(PwChars);
  734.     **PwChars = 0;
  735.     return(0);
  736. }
  737.  
  738. /************************************************************************
  739.  * InvalidatePasswords - wipe out our memory of passwords
  740.  ************************************************************************/
  741. void InvalidatePasswords(Boolean pwGood,Boolean auxpwGood)
  742. {
  743.     if (!pwGood)
  744.     {
  745.         *Password = 0;
  746.         POPSecure = 0;
  747.         if (PrefIsSet(PREF_SAVE_PASSWORD))
  748.             ChangeStrn(PREF_STRN,PREF_PASS_TEXT,Password);
  749.     }
  750.     if (!auxpwGood)
  751.     {
  752.         *SecondPass = 0;
  753.         if (PrefIsSet(PREF_SAVE_PASSWORD))
  754.             ChangeStrn(PREF_STRN,PREF_AUXPW,Password);
  755.     }
  756. }
  757.  
  758. /************************************************************************
  759.  * PasswordFilter - a ModalDialog filter for getting passwords
  760.  ************************************************************************/
  761. pascal Boolean PasswordFilter(DialogPtr dgPtr,EventRecord *event,short *item)
  762. {
  763.     if (!MiniMainLoop(event))
  764.         if (!CommandPeriod)
  765.             return(False);
  766.         else
  767.         {
  768.             *item = CANCEL_ITEM;
  769.             return(True);
  770.         }
  771.     if (event->what==keyDown || event->what==autoKey)
  772.     {
  773.         char key = event->message & charCodeMask;
  774.         switch (key)
  775.         {
  776.             case enterChar:
  777.             case returnChar:
  778.                 *item = 1;
  779.                 return(True);
  780.                 break;
  781.             case backSpace:
  782.                 if (**PwChars) --**PwChars;
  783.                 return(False);
  784.                 break;
  785.             case '.':
  786.                 if (event->modifiers & cmdKey)
  787.                 {
  788.                     *item=2;
  789.                     return(True);
  790.                     break;
  791.                 }
  792.                 /* fall through */
  793.             default:
  794.                 if (**PwChars < 255 && key != tabChar)
  795.                 {
  796.                     PCatC(*PwChars,key);
  797.                     event->message = ((event->message >> 8)<<8) | bulletChar;
  798.                 }
  799.                 else
  800.                 {
  801.                     SysBeep(20);
  802.                     event->what = nullEvent;
  803.                 }
  804.                 return(False);
  805.                 break;
  806.         }
  807.     }
  808.     else if (event->what==updateEvt)
  809.     {
  810.         if ((DialogPtr)event->message == dgPtr)
  811.             HiliteButtonOne(dgPtr);
  812.         else
  813.             UpdateMyWindow((MyWindowPtr)event->message);
  814.     }
  815.     else
  816.     {
  817.         if (TickCount()%120<100 && CurrentModifiers()&alphaLock)
  818.             ShowDItem(dgPtr,PASSWORD_WARNING);
  819.         else
  820.             HideDItem(dgPtr,PASSWORD_WARNING);
  821.     }
  822.  
  823.     return(False);
  824. }
  825.  
  826. /************************************************************************
  827.  * CopyPassword - retrieve the password
  828.  ************************************************************************/
  829. void CopyPassword(UPtr password)
  830. {
  831.     BlockMove(*PwChars,password,**PwChars + 1);
  832.     HPurge(PwChars);
  833. }
  834.  
  835. /************************************************************************
  836.  * MyAppendMenu - see that a menu item gets appended to a menu.  Avoids
  837.  * menu manager meta-characters.
  838.  ************************************************************************/
  839. void MyAppendMenu(MenuHandle menu, UPtr name)
  840. {
  841.     MyInsMenuItem(menu,name,CountMItems(menu));
  842. }
  843.  
  844. /************************************************************************
  845.  * MyInsMenuItem - see that a menu item gets appended to a menu.    Avoids
  846.  * menu manager meta-characters.
  847.  ************************************************************************/
  848. void MyInsMenuItem(MenuHandle menu, UPtr name, short afterItem)
  849. {
  850.     Str255 fixName;
  851.     
  852.     PCopy(fixName,"\pn");
  853.     InsMenuItem(menu,fixName,afterItem);
  854.     BlockMove(name+1,fixName+2,name[0]);
  855.     fixName[0] = name[0] + 1;
  856.     fixName[1] = '\0';
  857.     SetItem(menu,afterItem+1,fixName);
  858. }
  859.  
  860. /************************************************************************
  861.  * MyGetItem - get the text of a menu item.  Strip leading NULL, if any
  862.  ************************************************************************/
  863. void MyGetItem(MenuHandle menu, short item, UPtr name)
  864. {
  865.     GetItem(menu,item,name);
  866.     if (*name && !name[1])
  867.     {
  868.         BlockMove(name+2,name+1,name[0]-1);
  869.         name[0]--;
  870.     }
  871. }
  872.  
  873. /************************************************************************
  874.  * FindItemByName - find a named menu item
  875.  ************************************************************************/
  876. short FindItemByName(MenuHandle menu, UPtr name)
  877. {
  878.     short item;
  879.     Str255 itemTitle;
  880.     
  881.     for (item=CountMItems(menu);item;item--)
  882.     {
  883.         MyGetItem(menu,item,itemTitle);
  884.         if (EqualString(name,itemTitle,False,True)) break;
  885.     }
  886.     
  887.     return(item);
  888. }
  889.  
  890. /************************************************************************
  891.  * BinFindItemByName - find a named menu item, using binary search
  892.  ************************************************************************/
  893. short BinFindItemByName(MenuHandle menu, UPtr name)
  894. {
  895.     short item;
  896.     Str255 itemTitle;
  897.     short first,last;
  898.     short cmp;
  899.     
  900.     first = 1;
  901.     last = CountMItems(menu);
  902.     for (item=(first+last)/2;first<=last;item=(first+last)/2)
  903.     {
  904.         MyGetItem(menu,item,itemTitle);
  905.         cmp = RelString(name,itemTitle,False,True);
  906.         switch (cmp)
  907.         {
  908.             case -1:
  909.                 last = item-1;
  910.                 break;
  911.             case 1:
  912.                 first = item+1;
  913.                 break;
  914.             case 0:
  915.                 return(item);
  916.         }
  917.     }
  918.     
  919.     return(0);
  920. }
  921.  
  922. /************************************************************************
  923.  * SpecialKeys - mutate events involving particular keys
  924.  ************************************************************************/
  925. void SpecialKeys(EventRecord *event)
  926. {
  927.     long flags;
  928.     uShort menu,item;
  929.     
  930.     switch(event->message & charCodeMask)
  931.     {
  932.         case homeChar:
  933.         case endChar:
  934.         case pageUpChar:
  935.         case pageDownChar:
  936.             event->what = app1Evt;
  937.             break;
  938.         default:
  939.             switch((event->message & keyCodeMask)>>8)
  940.             {
  941.                 case undoKey:
  942.                     menu = EDIT_MENU;
  943.                     item = EDIT_UNDO_ITEM;
  944.                     break;
  945.                 case cutKey:
  946.                     menu = EDIT_MENU;
  947.                     item = EDIT_CUT_ITEM;
  948.                     break;
  949.                 case copyKey:
  950.                     menu = EDIT_MENU;
  951.                     item = EDIT_COPY_ITEM;
  952.                     break;
  953.                 case pasteKey:
  954.                     menu = EDIT_MENU;
  955.                     item = EDIT_PASTE_ITEM;
  956.                     break;
  957.                 case clearKey:
  958.                     menu = EDIT_MENU;
  959.                     item = EDIT_CLEAR_ITEM;
  960.                     break;
  961.                 default:
  962.                     return;
  963.             }
  964.             EnableMenuItems();
  965.             flags = (*GetMHandle(menu))->enableFlags;
  966.             if ((flags & 1) && (flags & (1<<item)))
  967.             {
  968.                 short oldMenu = TheMenu;
  969.                 HiliteMenu(menu);
  970.                 DoMenu(FrontWindow(),(menu<<16)|item,event->modifiers);
  971.                 if (oldMenu) HiliteMenu(oldMenu);
  972.             }
  973.             event->what = nullEvent;
  974.             break;
  975.     }
  976. }
  977.  
  978. /************************************************************************
  979.  * CurrentModifiers - return the current state of the modifers
  980.  ************************************************************************/
  981. short CurrentModifiers(void)
  982. {
  983.     EventRecord theEvent;
  984.     
  985.     OSEventAvail(nil,&theEvent);
  986.     return(theEvent.modifiers);
  987. }
  988.  
  989. /************************************************************************
  990.  * AttachHierMenu - attach a hierarchical menu to a menu item
  991.  ************************************************************************/
  992. void AttachHierMenu(short menu,short item,short hierId)
  993. {
  994.     MenuHandle mh = GetMHandle(menu);
  995.     SetItemCmd(mh,item,0x1b);
  996.     SetItemMark(mh,item,hierId);
  997. }
  998.  
  999. /************************************************************************
  1000.  * DirtyKey - does a keystroke cause a window to become dirty?
  1001.  ************************************************************************/
  1002. Boolean DirtyKey(long keyAndChar)
  1003. {
  1004.     short charCode = keyAndChar&charCodeMask;
  1005.     short keyCode = (keyAndChar&keyCodeMask)>>8;
  1006.     static short safeChars[]={
  1007.         homeChar,endChar,pageUpChar,pageDownChar,
  1008.         leftArrowChar,rightArrowChar,upArrowChar,downArrowChar};
  1009.     short *which;
  1010.     
  1011.     for (which=safeChars;which<safeChars+sizeof(safeChars)/sizeof(short);which++)
  1012.         if (charCode==*which) return(False);
  1013.     
  1014.     return(True);
  1015. }
  1016.  
  1017. /************************************************************************
  1018.  * LocalDateTimeStr - return a ctime format date and time,
  1019.  * but as a pascal string
  1020.  * <length>Sun Sep 16 01:03:52 1973\n\0
  1021.  * This is quite purposefully not internationally blessed
  1022.  ************************************************************************/
  1023. UPtr LocalDateTimeStr(UPtr string)
  1024. {
  1025.     DateTimeRec dtr;
  1026.     
  1027.     GetTime(&dtr);
  1028.     return(ComposeRString(string,DATE_STRING_FMT,
  1029.                                                              WEEKDAY_STRN+dtr.dayOfWeek,
  1030.                                                              MONTH_STRN+dtr.month,
  1031.                                                              dtr.day/10, dtr.day%10,
  1032.                                                              dtr.hour/10, dtr.hour%10,
  1033.                                                              dtr.minute/10, dtr.minute%10,
  1034.                                                              dtr.second/10, dtr.second%10,
  1035.                                                              dtr.year));
  1036. }
  1037.  
  1038. /************************************************************************
  1039.  * GMTDateTime - return the current seconds
  1040.  ************************************************************************/
  1041. long GMTDateTime(void)
  1042. {
  1043.     long secs;
  1044.     GetDateTime(&secs);
  1045.     secs -= ZoneSecs();
  1046.     return(secs);
  1047. }
  1048.  
  1049. /************************************************************************
  1050.  * LocalDateTime - return the current seconds
  1051.  ************************************************************************/
  1052. long LocalDateTime(void)
  1053. {
  1054.     long secs;
  1055.     GetDateTime(&secs);
  1056.     return(secs);
  1057. }
  1058.  
  1059. /************************************************************************
  1060.  * FixNewlines - remove cr, and turn nl into cr
  1061.  ************************************************************************/
  1062. void FixNewlines(UPtr string,long *count)
  1063. {
  1064.     char *from, *to;
  1065.     long n;
  1066.     
  1067.     for (to=from=string,n= *count;n;n--,from++)
  1068.         if (*from=='\012') *to++ = '\015';
  1069.         else if (*from!='\015') *to++ = *from;
  1070.     *count = to-string;
  1071. }
  1072.  
  1073. /************************************************************************
  1074.  * MiniEvents - call WNE, handle a few events, allow cmd-.
  1075.  ************************************************************************/
  1076. Boolean MiniEvents(void)
  1077. {
  1078.     EventRecord event;
  1079.     static long oldTicks;
  1080.     Boolean oldCommandPeriod = CommandPeriod;
  1081.     CommandPeriod = False;
  1082.     
  1083.     if (TickCount()-oldTicks > InBG ? 2 : 30)
  1084.     {
  1085.         if (WNE(everyEvent,&event,0))
  1086.         {
  1087.             (void) MiniMainLoop(&event);
  1088.             if (CommandPeriod) return(True);
  1089.         }
  1090.     }
  1091.     CommandPeriod = oldCommandPeriod;
  1092.     return(False);
  1093. }
  1094.  
  1095. /************************************************************************
  1096.  * GiveTime - allow for bg processing
  1097.  ************************************************************************/
  1098. void GiveTime(void)
  1099. {
  1100.     EventRecord tossMe;
  1101.     (void) WNE(0,&tossMe,0);
  1102. }
  1103.  
  1104. /************************************************************************
  1105.  * UnadornMessage - unadorn an event message
  1106.  ************************************************************************/
  1107. long UnadornMessage(EventRecord *event)
  1108. {
  1109.     long message;
  1110.     Handle curKCHR;
  1111.     static long state=0;
  1112.     short key;
  1113.     
  1114.     curKCHR = GetResource('KCHR',
  1115.                                             GetScript(GetEnvirons(smKeyScript),smScriptKeys));
  1116.     if (!curKCHR || !(event->modifiers&optionKey))
  1117.         message = event->message;
  1118.     else
  1119.     {
  1120.         /*
  1121.          * get what it would have been without the option key
  1122.          */
  1123.         key = ((event->message>>8)&0xff) | (event->modifiers&(~optionKey)&0xff00);
  1124.         message = KeyTrans(LDRef(curKCHR),key,&state);
  1125.         UL(curKCHR);
  1126.         
  1127.         /*
  1128.          * now massage this into an event "message"
  1129.          */
  1130.         message = (message & 0xff) | (event->message & 0xff00);
  1131.     }
  1132.     
  1133.     return(message);
  1134. }
  1135.  
  1136. /************************************************************************
  1137.  * MyMenuKey - fix MenuKey to ignore option key
  1138.  ************************************************************************/
  1139. long MyMenuKey(EventRecord *event)
  1140. {
  1141.     if (event->modifiers&cmdKey) EnableMenuItems();
  1142.     return(MenuKey(UnadornMessage(event)));
  1143. }
  1144.  
  1145. /************************************************************************
  1146.  * TrimPrefix - strip a prefix from a string
  1147.  ************************************************************************/
  1148. Boolean TrimPrefix(UPtr string, UPtr prefix)
  1149. {
  1150.     short oldLen = *string;
  1151.  
  1152.     if (oldLen < *prefix) return(False);
  1153.     
  1154.     *string = *prefix;
  1155.     if (EqualString(string,prefix,False,True))
  1156.     {
  1157.         BlockMove(string+1+*prefix,string+1,oldLen-*prefix);
  1158.         *string = oldLen - *prefix;
  1159.         return(True);
  1160.     }
  1161.     else
  1162.     {
  1163.         *string = oldLen;
  1164.         return(False);
  1165.     }
  1166. }
  1167.  
  1168. /************************************************************************
  1169.  * ChangeStrn - change a string in an Str# resource
  1170.  ************************************************************************/
  1171. UPtr ChangeStrn(short resId,short num,UPtr string)
  1172. {
  1173.     Handle resH = GetResource('STR#',resId);
  1174.     UPtr spot;
  1175.     short count;
  1176.     short i;
  1177.     long hSize;
  1178.     short diff;
  1179.     
  1180.     if (!resH) return(nil);
  1181.     spot = LDRef(resH);
  1182.     hSize = GetHandleSize(resH);
  1183.     count = 256*spot[0] + spot[1];
  1184.     if (num<=count)
  1185.     {
  1186.         spot += 2;
  1187.         for (i=1;i<num;i++) spot += *spot + 1;
  1188.         diff = *string-*spot;
  1189.         if (diff<0)
  1190.         {
  1191.             diff *= -1;
  1192.             if (num<count)
  1193.                 BlockMove(spot+diff,spot,hSize-(spot-*resH)-diff);
  1194.             SetHandleBig(resH,hSize-diff);
  1195.         }
  1196.         else if (diff>0)
  1197.         {
  1198.             SetHandleBig(resH,hSize+diff);
  1199.             if (i=MemError()) {WarnUser(MEM_ERR,i);UL(resH);return(nil);}
  1200.             if (num<count)
  1201.                 BlockMove(spot,spot+diff,hSize-(spot-*resH));
  1202.         }
  1203.     }
  1204.     else
  1205.     {
  1206.         UL(resH);
  1207.         SetHandleBig(resH,hSize+*string+num-count);
  1208.         if (i=MemError()) {WarnUser(MEM_ERR,i);return(nil);}
  1209.         spot = LDRef(resH);
  1210.         if (num>count+1)
  1211.             WriteZero(spot+hSize,num-count-1);
  1212.         spot[0] = num/256;
  1213.         spot[1] = num%256;
  1214.         spot += hSize + num-count-1;
  1215.     }
  1216.     hSize = GetHandleSize(resH);
  1217.     BlockMove(string,spot,*string+1);
  1218.     UL(resH);
  1219.     HNoPurge(resH);
  1220.     ChangedResource(resH);
  1221.     return(string);
  1222. }
  1223.  
  1224. /************************************************************************
  1225.  * RecountStrn - make sure an STR# resource really has the right number
  1226.  * of strings
  1227.  ************************************************************************/
  1228. void RecountStrn(short resId)
  1229. {
  1230.     Handle resH = GetResource('STR#',resId);
  1231.     UPtr spot,end;
  1232.     short count;
  1233.     short realCount=0;
  1234.     
  1235.     if (!resH) return;
  1236.     spot = *resH;
  1237.     end = spot+GetHandleSize(resH);
  1238.     count = spot[0]*256 + spot[1];
  1239.     for (spot+=2;spot<end;spot += *spot+1) realCount++;
  1240.     
  1241.     if (realCount!=count)
  1242.     {
  1243.         spot=*resH;
  1244.         spot[0] = realCount/256;
  1245.         spot[1] = realCount%256;
  1246.         ChangedResource(resH);
  1247.         HNoPurge(resH);
  1248.     }
  1249. }
  1250.  
  1251. /************************************************************************
  1252.  *
  1253.  ************************************************************************/
  1254. void NukeMenuItemByName(short menuId,UPtr itemName)
  1255. {
  1256.     MenuHandle mh=GetMHandle(menuId);
  1257.     short itemNum=FindItemByName(mh,itemName);
  1258.     
  1259.     if (itemNum) NukeMenuItem(mh,itemNum);
  1260. }
  1261.  
  1262. void NukeMenuItem(MenuHandle mh,short item)
  1263. {
  1264.     if (HasSubmenu(mh,item))
  1265.     {
  1266.         short subId,subItem;
  1267.         MenuHandle subMh;
  1268.         GetItemMark(mh,item,&subId);
  1269.         subMh=GetMHandle(subId);
  1270.         for (subItem=CountMItems(subMh);subItem;subItem--)
  1271.             NukeMenuItem(mh,subItem);
  1272.     }
  1273.     DelMenuItem(mh,item);
  1274. }
  1275.  
  1276. /************************************************************************
  1277.  *
  1278.  ************************************************************************/
  1279. void RenameItem(short menuId,UPtr oldName,UPtr newName)
  1280. {
  1281.     MenuHandle mh=GetMHandle(menuId);
  1282.     
  1283.     SetItem(mh,FindItemByName(mh,oldName),newName);
  1284. }
  1285.  
  1286. /************************************************************************
  1287.  *
  1288.  ************************************************************************/
  1289. Boolean HasSubmenu(MenuHandle mh, short item)
  1290. {
  1291.     short cmd;
  1292.     GetItemCmd(mh,item,&cmd);
  1293.     return(cmd==0x1b);
  1294. }
  1295.  
  1296. /************************************************************************
  1297.  * GreyControl - grey out a control
  1298.  ************************************************************************/
  1299. void GreyControl(ControlHandle cntl)
  1300. {
  1301.     Rect r = (*cntl)->contrlRect;
  1302.     InsetRect(&r,2,2);
  1303.     GreyOutRoundRect(&r,3,3);
  1304. }
  1305.  
  1306. /************************************************************************
  1307.  * SetGreyControl - grey a control, if it isn't already
  1308.  ************************************************************************/
  1309. Boolean SetGreyControl(ControlHandle cntl, Boolean shdBeGrey)
  1310. {
  1311.     if (((*cntl)->contrlRfCon=='GREY')!=shdBeGrey)
  1312.     {
  1313.         Rect r;
  1314.         (*cntl)->contrlRfCon = shdBeGrey ? 'GREY' : 0;
  1315.         r = (*cntl)->contrlRect;
  1316.         InsetRect(&r,2,2);
  1317.         InvalRect(&r);
  1318.     }
  1319.     return(shdBeGrey);
  1320. }
  1321.  
  1322. /************************************************************************
  1323.  * IsAUX - is A/UX running?
  1324.  ************************************************************************/
  1325. Boolean IsAUX(void)
  1326. {
  1327.     return(((*(short *)0xb22)&(1<<9))!=0);
  1328. }
  1329.  
  1330. /************************************************************************
  1331.  * ZoneSecs - get the timezone offset, in seconds
  1332.  ************************************************************************/
  1333. long ZoneSecs(void)
  1334. {
  1335.     MachineLocation ml;
  1336.     long delta;
  1337. #define GMTDELTA gmtFlags.gmtDelta
  1338.     ReadLocation(&ml);
  1339.     if (ml.latitude==ml.longitude && ml.GMTDELTA==ml.longitude && ml.GMTDELTA==0)
  1340.         return(-1);
  1341.  
  1342.     delta = ml.GMTDELTA&0xffffff;
  1343.     if ((delta>>23)&1) delta |= 0xff000000;
  1344.     
  1345.     return(delta);
  1346. }
  1347.  
  1348. /************************************************************************
  1349.  * WNE - call WaitNextEvent.    Set InBG properly.
  1350.  ************************************************************************/
  1351. Boolean WNE(short eventMask,EventRecord *event,long sleep)
  1352. {
  1353.     EventRecord localEvt;
  1354.     Boolean result;
  1355.     short mods = CurrentModifiers();
  1356. #ifdef NEVER
  1357.     static RgnHandle oldMouseRgn;
  1358.     if (!oldMouseRgn) oldMouseRgn = NewRgn();
  1359.     if (BUG1 && !EqualRgn(MouseRgn,oldMouseRgn))
  1360.     {
  1361.         ShowGlobalRgn(MouseRgn,"\pWNE MouseRgn");
  1362.         CopyRgn(MouseRgn,oldMouseRgn);
  1363.     }
  1364. #endif
  1365.     
  1366.     result = WaitNextEvent(eventMask,&localEvt,sleep,MouseRgn);
  1367. #ifdef DEBUG
  1368.     if (LogLevel&LOG_EVENT)
  1369.     {
  1370.         if (localEvt.what==keyDown)
  1371.             ComposeLogS(LOG_EVENT,nil,"\p%d %d %d ",
  1372.                 localEvt.what,localEvt.message&0xff,localEvt.modifiers);
  1373.         else if (localEvt.what==mouseDown)
  1374.             ComposeLogS(LOG_EVENT,nil,"\p%d %d %d %d",
  1375.                 localEvt.what,localEvt.modifiers,localEvt.where.h,localEvt.where.v);
  1376.     }
  1377. #endif
  1378.     
  1379.     if (mods!=localEvt.modifiers) SFWTC = True;
  1380.  
  1381.     if (localEvt.what==app4Evt && ((localEvt.message)>>24)&1 == 1)
  1382.         InBG = ((localEvt.message&1) != 1); /* suspend/resume */
  1383.     else if (HasPM)
  1384.     {
  1385.         ProcessSerialNumber me, him;                                /* System 7 */
  1386.         GetCurrentProcess(&me);
  1387.         GetFrontProcess(&him);
  1388.         InBG = me!=him;
  1389.     }
  1390.     if (event) *event=localEvt;
  1391.     return(result);
  1392. }
  1393.  
  1394. /************************************************************************
  1395.  * Provide the same benefit as a politician
  1396.  ************************************************************************/
  1397. void NOOP(void) {}
  1398. /************************************************************************
  1399.  * DlgUpdate - update a dialog window
  1400.  ************************************************************************/
  1401. void DlgUpdate(MyWindowPtr win)
  1402. {
  1403.     UpdtDialog(win,((GrafPtr)win)->visRgn);
  1404. }
  1405.  
  1406. /************************************************************************
  1407.  * RoundDiv - Divide with rounding away from the origin
  1408.  ************************************************************************/
  1409. long RoundDiv(long quantity,long unit)
  1410. {
  1411.   if (quantity<0) quantity -= unit-1;
  1412.     else quantity += unit-1;
  1413.     return(quantity/unit);
  1414. }
  1415.  
  1416. /************************************************************************
  1417.  * TZName2Offset - interpret the time zone with a resource
  1418.  ************************************************************************/
  1419. long TZName2Offset(CStr zoneName)
  1420. {
  1421.     UPtr this,end;
  1422.     Handle tznH = GetResource('zon#',TZ_NAMES);
  1423.     long offset = 0;
  1424.     Str15 pName;
  1425.     
  1426.     CtoPCpy(pName,zoneName);
  1427.     
  1428.     if (tznH)
  1429.     {
  1430.         this = LDRef(tznH);
  1431.         end = this + GetHandleSize(tznH);
  1432.         for (;this<end;this+=*this+1+2*sizeof(short))
  1433.             if (EqualString(this,pName,False,True))
  1434.             {
  1435.                 short hrs,mins;
  1436.                 this += *this +1;
  1437.                 hrs = this[0]*256+this[1];
  1438.                 mins = this[2]*256+this[3];
  1439.                 offset = hrs*3600 + 60*mins;
  1440.                 break;
  1441.             }
  1442.         UL(tznH);
  1443.     }
  1444.     return(offset);
  1445. }
  1446.  
  1447. /************************************************************************
  1448.  * CenterRectIn - center one rect in another
  1449.  ************************************************************************/
  1450. void CenterRectIn(Rect *inner,Rect *outer)
  1451. {
  1452.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  1453.                                      (outer->top+outer->bottom-inner->top-inner->bottom)/2);                                                                    
  1454. }
  1455.  
  1456. /************************************************************************
  1457.  * TopCenterRectIn - center one rect in (the bottom of) another
  1458.  ************************************************************************/
  1459. void TopCenterRectIn(Rect *inner,Rect *outer)
  1460. {
  1461.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  1462.                                      outer->top-inner->top);                                                                    
  1463. }
  1464.  
  1465. /************************************************************************
  1466.  * BottomCenterRectIn - center one rect in (the bottom of) another
  1467.  ************************************************************************/
  1468. void BottomCenterRectIn(Rect *inner,Rect *outer)
  1469. {
  1470.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  1471.                                      outer->bottom-inner->bottom);                                                                    
  1472. }
  1473.  
  1474. /************************************************************************
  1475.  * ThirdCenterRectIn - center one rect in (the top 1/3 of) another
  1476.  ************************************************************************/
  1477. void ThirdCenterRectIn(Rect *inner,Rect *outer)
  1478. {
  1479.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  1480.                                      outer->top-inner->top +
  1481.                                      (outer->bottom-outer->top-inner->bottom+inner->top)/3);                                                                    
  1482. }
  1483.  
  1484. /************************************************************************
  1485.  * MyLClick - call LClick, but disallow cmd-double-click
  1486.  ************************************************************************/
  1487. Boolean MyLClick(Point pt,short modifiers,ListHandle lHandle)
  1488. {
  1489.     return(LClick(pt,modifiers,lHandle)&!(modifiers&cmdKey));
  1490. }
  1491.  
  1492. #pragma segment StringUtils
  1493. /**********************************************************************
  1494.  * return a string from an STR# resource
  1495.  **********************************************************************/
  1496. UPtr GetRString(UPtr theString,int theIndex)
  1497. {
  1498.     StringHandle s;
  1499.     short oldRes = CurResFile();
  1500.     if (SettingsRefN) UseResFile(SettingsRefN);
  1501.     if (theIndex != 1001 && (s=GetString(theIndex)) && HomeResFile(s))
  1502.     {
  1503.         PCopy(theString,*s);
  1504.         ReleaseResource(s);
  1505.     }
  1506.     else
  1507.     {
  1508.         theString[0] = 0;
  1509.         GetIndString(theString,200*(theIndex/200),theIndex%200);
  1510.     }
  1511.     theString[*theString+1] = 0;
  1512.     UseResFile(oldRes);
  1513.     return(theString);
  1514. }
  1515.  
  1516. /**********************************************************************
  1517.  * copy a pascal string into a c string
  1518.  **********************************************************************/
  1519. UPtr PtoCcpy(UPtr cStr, UPtr pStr)
  1520. {
  1521.     BlockMove(pStr+1,cStr,*pStr);
  1522.     cStr[*pStr] = 0;
  1523.     return(cStr);
  1524. }
  1525.  
  1526. /**********************************************************************
  1527.  * concatenate a pascal string on the end of another
  1528.  **********************************************************************/
  1529. UPtr PCat(UPtr string,UPtr suffix)
  1530. {
  1531.     short sufLen;
  1532.     
  1533.     sufLen = *suffix;
  1534.     
  1535.     BlockMove(suffix+1,string+*string+1,sufLen);
  1536.     *string += sufLen;
  1537.     
  1538.     return(string);
  1539. }
  1540.  
  1541. /**********************************************************************
  1542.  * concatenate a pascal string on the end of another
  1543.  * escape certain chars in the string
  1544.  **********************************************************************/
  1545. UPtr PEscCat(UPtr string, UPtr suffix, short escape, char *escapeWhat)
  1546. {
  1547.     short sufLen;
  1548.     char *suffSpot,*stringSpot;
  1549.     
  1550.     sufLen = *suffix;
  1551.     stringSpot = string+*string+1;
  1552.     
  1553.     for (suffSpot=suffix+1;sufLen--;suffSpot++)
  1554.     {
  1555.         if (*suffSpot==escape || strchr(escapeWhat,*suffSpot))
  1556.             *stringSpot++ = escape;
  1557.         *stringSpot++ = *suffSpot;
  1558.     }
  1559.     *string = stringSpot-string-1;
  1560.     
  1561.     return(string);
  1562. }
  1563.  
  1564. /**********************************************************************
  1565.  * Get a long out of a resource file
  1566.  **********************************************************************/
  1567. long GetRLong(int index)
  1568. {
  1569.     Str255 scratch;
  1570.     long aLong;
  1571.     
  1572.     if (GetRString(scratch,index)==nil)
  1573.         return(0L);
  1574.     else
  1575.     {
  1576.         StringToNum(scratch,&aLong);
  1577.         return(aLong);
  1578.     }
  1579. }
  1580.  
  1581. /**********************************************************************
  1582.  * striscmp - compare two strings, up to the length of the shorter string,
  1583.  * and ignoring case
  1584.  **********************************************************************/
  1585. #define isupper(c)    ('A'<=c && c<='Z')
  1586. #define tolower(c)    (c + ('a'-'A'))
  1587. int striscmp(UPtr s1,UPtr s2)
  1588. {
  1589.     register c1, c2;
  1590.     for (c1= *s1, c2= *s2; c1 && c2; c1 = *++s1, c2= *++s2)
  1591.     {
  1592.         if (isupper(c1)) c1=tolower(c1);
  1593.         if (isupper(c2)) c2=tolower(c2);
  1594.         if (c1-c2) return (c1-c2);
  1595.     }
  1596.     return(0);
  1597. }
  1598.  
  1599. /**********************************************************************
  1600.  * TrimWhite - remove whitespace characters from the end of a string
  1601.  **********************************************************************/
  1602. void TrimWhite(PStr s)
  1603. {
  1604.     register int len=*s;
  1605.     register UPtr cp=s+len;
  1606.     
  1607.     while (len && isspace(*cp)) cp--,len--;
  1608.     
  1609.     *s = len;
  1610. }
  1611.  
  1612. /**********************************************************************
  1613.  * TrimInitialWhite - remove whitespace characters from the beginning of a string
  1614.  **********************************************************************/
  1615. void TrimInitialWhite(PStr s)
  1616. {
  1617.     UPtr cp=s+1;
  1618.     short len;
  1619.     
  1620.     for (cp=s+1;cp<=s+*s && isspace(*cp);cp++);
  1621.     if (cp>s+1 && cp<=s+*s)
  1622.     {
  1623.         len = *s - (cp-(s+1));
  1624.         BlockMove(cp,s+1,len);
  1625.         *s = len;
  1626.     }
  1627. }
  1628.  
  1629. /************************************************************************
  1630.  * Tokenize - set pointers to the beginning and end of a delimited token
  1631.  ************************************************************************/
  1632. UPtr Tokenize(UPtr string, int size, UPtr *start, UPtr *end, UPtr delims)
  1633. {
  1634.     UPtr stop = string+size;
  1635.     char safe = *stop;
  1636.     UPtr last;
  1637.     
  1638.     *stop = 0;
  1639.     while (strchr(delims,*string)) string++;
  1640.     *stop = *delims;
  1641.     for (last=string; !strchr(delims,*last); last++);
  1642.     *stop = safe;
  1643.     if (string==stop) return(nil);
  1644.     *start = string;
  1645.     *end = stop;
  1646.     return(string);
  1647. }
  1648.  
  1649.  
  1650. /************************************************************************
  1651.  * RemoveSpaces - remove the spaces from some text
  1652.  ************************************************************************/
  1653. long RemoveSpaces(UPtr text,long size)
  1654. {
  1655.     UPtr from, to, limit;
  1656.     
  1657.     for (to=text,limit=text+size;*to!=' ' && to<limit;to++);
  1658.     if (to<limit)
  1659.         for (from=to;from<limit;from++) if (*from!=' ') *to++ = *from;
  1660.     return(to-text);
  1661. }
  1662.  
  1663. /************************************************************************
  1664.  * GetRStr - get a string from an 'STR ' resource
  1665.  ************************************************************************/
  1666. UPtr GetRStr(UPtr string,short id)
  1667. {
  1668.     Handle strH = GetString(id);
  1669.     if (strH)
  1670.     {
  1671.         PCopy(string,*strH);
  1672.         ReleaseResource(strH);
  1673.     }
  1674.     else
  1675.         *string = 0;
  1676.     return(string);
  1677. }
  1678.  
  1679. /************************************************************************
  1680.  * atoi - turn a string into an integer
  1681.  ************************************************************************/
  1682. long atoi(UPtr p)
  1683. {
  1684.     long sign=1;
  1685.     long value=0;
  1686.     
  1687.     while (isspace(*p)) p++;
  1688.     if (*p=='-') {sign = -1; p++;}
  1689.     else if (*p=='+') p++;
  1690.     
  1691.     while (isdigit(*p))
  1692.     {
  1693.         value *= 10;
  1694.         value += *p - '0';
  1695.         p++;
  1696.     }
  1697.     
  1698.     return(value*sign);
  1699. }
  1700.  
  1701. /************************************************************************
  1702.  * PLCat - concat a long onto a string (preceed it with a space)
  1703.  ************************************************************************/
  1704. UPtr PLCat(UPtr string,long num)
  1705. {
  1706.     short n;            /* length of old string + 1 */
  1707.     n = *string+1;
  1708.     NumToString(num,string+n);
  1709.     string[0] += string[n]+1;
  1710.     string[n] = ' ';
  1711.     return(string);
  1712. }
  1713.  
  1714. /************************************************************************
  1715.  * EndsWith - does one string end with another?
  1716.  ************************************************************************/
  1717. Boolean EndsWith(PStr name,PStr suffix)
  1718. {
  1719.     Boolean res;
  1720.     Byte c;
  1721.     UPtr spot;
  1722.     if (*name<*suffix) return(False);            /* too short */
  1723.     
  1724.     spot = name + *name - *suffix ;                /* before start of putative suffix */
  1725.     c = *spot;                                                        /* save byte */
  1726.     *spot = *suffix;                                            /* pretend equal length */
  1727.     res = EqualString(suffix,spot,False,True);
  1728.     *spot = c;                                                        /* restore byte */
  1729.     return(res);
  1730. }
  1731.  
  1732. /************************************************************************
  1733.  * RemoveParens - remove parenthesized information
  1734.  ************************************************************************/
  1735. void RemoveParens(UPtr string)
  1736. {
  1737.     UPtr to, from, end;
  1738.     short pLevel=0;
  1739.     
  1740.     for (to=from=string+1,end=string+*string; from<=end; from++)
  1741.         switch(*from)
  1742.         {
  1743.             case '(':
  1744.                 pLevel++;
  1745.                 break;
  1746.             case ')':
  1747.                 if (pLevel) pLevel--;
  1748.                 else *to++ = *from;
  1749.                 break;
  1750.             case ' ':
  1751.                 if (!pLevel) break;
  1752.                 /* fall through is deliberate */
  1753.             default:
  1754.                 *to++ = *from;
  1755.                 break;
  1756.         }
  1757.     *string = to-string-1;
  1758. }
  1759.  
  1760. /************************************************************************
  1761.  * ComposeString - sprintf, only smaller
  1762.  * %s - c string
  1763.  * %d - int
  1764.  * %c - char (int)
  1765.  * %p - pascal string
  1766.  * %i - internet address
  1767.  * %I - internet address, turned into hostname
  1768.  * %r - string from a resource
  1769.  ************************************************************************/
  1770. UPtr ComposeString(UPtr into,UPtr format,...)
  1771. {
  1772.     va_list args;
  1773.     va_start(args,format);
  1774.     (void) VaComposeString(into,format,args);
  1775.     va_end(args);
  1776.     return(into);
  1777. }
  1778. UPtr ComposeRString(UPtr into,short format,...)
  1779. {
  1780.     va_list args;
  1781.     va_start(args,format);
  1782.     (void) VaComposeRString(into,format,args);
  1783.     va_end(args);
  1784.     return(into);
  1785. }
  1786. UPtr VaComposeRString(UPtr into,short format,va_list args)
  1787. {
  1788.     Str255 stringFormat;
  1789.     
  1790.     GetRString(stringFormat,format);
  1791.     return (VaComposeString(into,stringFormat,args));
  1792. }
  1793. UPtr VaComposeString(UPtr into,UPtr format,va_list args)
  1794. {
  1795.     UPtr intoP;
  1796.     UPtr formatP;
  1797.     Str255 scratch;
  1798.     Uptr argString;
  1799.     struct hostInfo hi;
  1800.     short n;
  1801.     
  1802.     intoP = into+1;
  1803.     for (formatP=format+1;formatP<format+*format+1;formatP++)
  1804.         if (*formatP!='%')
  1805.             *intoP++ = *formatP;
  1806.         else
  1807.         {
  1808.             formatP++;
  1809.             switch (*formatP)
  1810.             {
  1811.                 case 'c':
  1812.                     *intoP++ = va_arg(args,unsigned int);
  1813.                     break;
  1814.                 case '%':
  1815.                     *intoP++ = '%';
  1816.                     break;
  1817.                 case 's':
  1818.                     argString = va_arg(args,UPtr);
  1819.                     while (*argString) *intoP++ = *argString++;
  1820.                     break;
  1821.                 default:
  1822.                     switch (*formatP)
  1823.                     {
  1824.                         case 'p':
  1825.                             argString = va_arg(args,UPtr);
  1826.                             break;
  1827.                         case 'i':
  1828.                             argString = NumToDot(va_arg(args,unsigned int),scratch);
  1829.                             break;
  1830.                         case 'I':
  1831.                             argString = scratch;
  1832.                             if (!GetHostByAddr(&hi,va_arg(args,unsigned int)))
  1833.                             {
  1834.                                 *scratch = strlen(hi.cname);
  1835.                                 BlockMove(hi.cname,scratch+1,*scratch+1);
  1836.                             }
  1837.                             else
  1838.                                 GetRString(scratch,UNTITLED);
  1839.                             break;
  1840.                         case 'd':
  1841.                             NumToString(va_arg(args,int),scratch);
  1842.                             argString=scratch;
  1843.                             break;
  1844.                         case 'r':
  1845.                             GetRString(scratch,va_arg(args,int));
  1846.                             argString=scratch;
  1847.                             break;
  1848. #ifdef DEBUG
  1849.                         case 'b':
  1850.                             n = va_arg(args,int);
  1851.                             *scratch = 32;
  1852.                             for (argString=scratch+32;argString>scratch;argString--)
  1853.                             {
  1854.                                 *argString = n&1 ? '1' : '0';
  1855.                                 n >>= 1;
  1856.                             }
  1857.                             break;
  1858. #endif
  1859.                     }
  1860.                     n = *argString;
  1861.                     for (argString++;n--;argString++) *intoP++ = *argString;
  1862.                     break;
  1863.             }
  1864.         }
  1865.     *into = intoP-into-1;
  1866.     *intoP = 0;
  1867.     return(into);
  1868. }
  1869.  
  1870. /************************************************************************
  1871.  * TransLitString - transliaterate with the default viewing table
  1872.  ************************************************************************/
  1873. void TransLitString(UPtr string)
  1874. {
  1875.     short id = GetRLong(PREF_IN_XLATE+PREF_STRN);
  1876.     Handle xlh;
  1877.     UPtr end;
  1878.     UPtr table;
  1879.     
  1880.     if (id!=NO_TABLE && (xlh=GetResource('taBL',id)))
  1881.     {
  1882.         table = LDRef(xlh);
  1883.         for (end = string+*string;end>string;end--)
  1884.             *end = table[*end];
  1885.         UL(xlh);
  1886.     }
  1887. }
  1888.